package com.tronsis.library.http;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.tronsis.library.Constants;
import com.tronsis.library.R;
import com.tronsis.library.util.DateUtil;
import com.tronsis.library.util.LogUtil;
import com.tronsis.library.util.SharedPreferencesUtil;
import com.tronsis.library.util.ToastUtil;

import java.io.IOException;
import java.lang.reflect.Type;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Date;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;

public abstract class HttpCallBack implements Callback {

    private Activity mActivity;
    private Type mResponseType;
    private int mResponseCode;
    private boolean isToast = true;

    public HttpCallBack(Activity activity, Type mResponseType) {
        this.mActivity = activity;
        this.mResponseType = mResponseType;
    }

    public HttpCallBack(Activity activity, Type mResponseType, boolean isToast) {
        this.mActivity = activity;
        this.mResponseType = mResponseType;
        this.isToast = isToast;
    }

    @Override
    public void onFailure(Call call, final IOException exception) {
        if (mActivity != null) {
            mActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    onRequestFailure(exception);
                }
            });
        }
    }

    @Override
    public void onResponse(Call call, final Response response) throws IOException {
        final String res = response.body().string();
        String authorization = response.headers().get("Authorization");
        if (authorization != null) {
            LogUtil.e("HttpCallBack Header Authorization:", authorization);
            SharedPreferencesUtil.putString(mActivity, Constants.SP_HEADER_AUTHORIZATION, authorization);
        }

        Date date = response.headers().getDate("Date");
        if (date != null) {
            LogUtil.d("HttpCallBack Server Date", "Server Date: " + date.toString());
            //SystemClock.elapsedRealtime()
            long differenceValue = date.getTime() - System.currentTimeMillis();
            SharedPreferencesUtil.putLong(mActivity, DateUtil.SP_SERVER_CURRENT_TIME_DIFFERENCE_VALUE, differenceValue);
        }

        String requestId = response.headers().get("Request-Id");
        LogUtil.e("HttpCallBack Request-Id", "Request-Id: " + requestId);

        LogUtil.eLong("HttpCallback", res + "");


        if (mActivity != null) {
            mActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    onRequestSuccess(res);
                }
            });
        }
    }

    public Activity getActivity() {
        return mActivity;
    }

    /**
     * 请求开始
     */
    public abstract void onStart();

    /**
     * 请求成功回调
     *
     * @param status 请求状态码
     * @param result 请求成功的返回值
     */
    public abstract void onCallBack(int status, Object result);

    /**
     * 请求失败
     *
     * @param exception
     */
    private void onRequestFailure(IOException exception) {
        LogUtil.e("HttpException", exception.getMessage() + "");
        if (exception != null && exception instanceof ConnectException || exception instanceof UnknownHostException) {
            onNetError();
        } else if (exception != null && exception instanceof SocketTimeoutException) {
            onConnectTimeOut();
        } else {
            onServerError();
        }
    }

    /**
     * 请求成功
     *
     * @param res
     */
    private void onRequestSuccess(String res) {
        try {
            HttpResponse httpResponse = parseResponse(res);
            mResponseCode = httpResponse.getCode();
            String msg = httpResponse.getMsg();
            switch (httpResponse.getCode()) {
                case 400:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_400));
                    onCallBack(400, null);
                    break;
                case 401:
                    if (msg != null) {
                        if (msg.contains("UNAUTHORIZED") || msg.contains("Bad Credentials")) {
                            ToastUtil.showMessage(isToast, mActivity, "登录已过期，请重新登录");
                            logout(mActivity);
                            return;
                        }
                    }
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_401));
                    onCallBack(401, null);
                    break;
                case 403:
                    ToastUtil.showMessage(isToast, mActivity, TextUtils.isEmpty(msg) ? mActivity.getString(R.string.response_403) : msg);
                    onCallBack(403, null);
                    break;
                case 404:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_404));
                    onCallBack(404, null);
                    break;
                case 409:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_409));
                    onCallBack(409, null);
                    break;
                case 429:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_429));
                    onCallBack(429, null);
                    break;
                case 500:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_500));
                    onCallBack(500, null);
                    break;
                case 520:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_520));
                    onCallBack(520, null);
                    break;
                case 521:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_521));
                    onCallBack(521, null);
                    break;
                case 522:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_522));
                    onCallBack(522, null);
                    break;
                case 523:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_523));
                    onCallBack(523, null);
                    break;
                case 524:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_524));
                    onCallBack(524, null);
                    break;
                case 1002:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_1002));
                    onCallBack(1002, null);
                    break;
                case 2002:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_2002));
                    onCallBack(2002, null);
                    break;
                case 2003:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_2003));
                    onCallBack(2003, null);
                    break;
                case 2004:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_2004));
                    onCallBack(2004, null);
                    break;
                case 2005:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_2005));
                    onCallBack(2005, null);
                    break;
                case 2006:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_2006));
                    onCallBack(2006, null);
                    break;
                case 2007:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_2007));
                    onCallBack(2007, null);
                    break;
                case 2008:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_2008));
                    onCallBack(2008, null);
                    break;
                case 2009:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_2009));
                    onCallBack(2009, null);
                    break;
                case 2101:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_2101));
                    onCallBack(2101, null);
                    break;
                case 2010:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_2010));
                    onCallBack(2010, null);
                    break;
                case 2011:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_2011));
                    onCallBack(2011, null);
                    break;
                case 2012:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_2012));
                    onCallBack(2012, null);
                    break;
                case 2013:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_2013));
                    onCallBack(2013, null);
                    break;
                case 2201:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_2201));
                    onCallBack(2201, null);
                    break;
                case 3001:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_3001));
                    onCallBack(3001, null);
                    break;
                case 4001:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_4001));
                    onCallBack(4001, null);
                    break;
                case 4002:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_4002));
                    onCallBack(4002, null);
                    break;
                case 4003:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_4003));
                    onCallBack(4003, null);
                    break;
                case 4004:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_4004));
                    onCallBack(4004, null);
                    break;
                case 5001:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_5001));
                    onCallBack(5001, null);
                    break;
                case 6001:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_6001));
                    onCallBack(6001, null);
                    break;
                case 6002:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_6002));
                    onCallBack(6002, null);
                    break;
                case 6003:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_6003));
                    onCallBack(6003, null);
                    break;
                case 6004:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_6004));
                    onCallBack(6004, null);
                    break;
                case 7001:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_7001));
                    onCallBack(7001, null);
                    break;
                case 8001:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_8001));
                    onCallBack(8001, null);
                    break;
                case 8002:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_8002));
                    onCallBack(8002, null);
                    break;
                case 8003:
                    ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.response_8003));
                    onCallBack(8003, null);
                    break;
                case 200:
                    Object result = null;
                    try {
                        if (httpResponse.getData() != null) {
                            String data = (new Gson().toJson(httpResponse.getData()));
                            result = new Gson().fromJson(data, mResponseType);
                        }
                    } catch (Exception e) {
                        LogUtil.e("----exception 1", "解析异常");
                        onCallBack(110, null);
                        e.printStackTrace();
                    }
                    try {
                        onCallBack(httpResponse.getCode(), result);
                    } catch (Exception e) {
                        LogUtil.e("----exception 2", "onCallBack 出错");
                        //                        ToastUtil.showMessage(isToast,mActivity, mActivity.getString(R.string.data_error));
                        e.printStackTrace();
                    }
                    break;
                default:
                    ToastUtil.showMessage(isToast, mActivity, TextUtils.isEmpty(msg) ? "服务器错误" : msg);
                    onCallBack(httpResponse.getCode(), null);
                    break;
            }
        } catch (Throwable e) {
            LogUtil.e("----exception", "外部数据异常");
            onCallBack(110, null);
            e.printStackTrace();
        }
    }

    private void logout(Activity activity) {
        if (isCurrentActivity(activity)) {
            return;
        }
        /*
            FLAG_ACTIVITY_CLEAR_TASK 这个标示将在这个活动开始之前清除该栈中所有的任务,将里面的Activity都finish掉
            FLAG_ACTIVITY_TASK_ON_HOME 这个flag将造成新任务在home的上面，就是在启动的Activity点击back之后就会回到home界面
         */
        Class clazz = null;
        try {
            clazz = Class.forName("com.tronsis.distribution.activity.login.LoginActivity");
            Intent intent = new Intent(activity, clazz);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
            activity.startActivity(intent);
            activity.finish();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    private boolean isCurrentActivity(Activity activity) {
        ActivityManager manager = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
        try {
            if (manager != null && manager.getRunningTasks(1) != null && manager.getRunningTasks(1).size() > 0) {
                String name = manager.getRunningTasks(1).get(0).topActivity.getClassName();
                if (name.contains("LoginActivity")) {
                    return true;
                }
            }
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        return false;
    }


    private void responseError(int stringId) {
        ToastUtil.showMessage(isToast, mActivity, mActivity.getString(stringId) + "[" + String.valueOf(mResponseCode) + "]");
        onCallBack(mResponseCode, null);
    }

    /**
     * 解析服务器返回的json数据
     *
     * @param responseString
     * @return
     * @throws Throwable
     */
    private HttpResponse parseResponse(String responseString) {
        HttpResponse response = null;

        if (!TextUtils.isEmpty(responseString)) {
            Type objectType = new TypeToken<HttpResponse>() {
            }.getType();
            try {
                response = new Gson().fromJson(responseString, objectType);
            } catch (Exception e) {
                LogUtil.e("HttpResponse", e.toString());
                e.printStackTrace();
            }
        }
        return response;
    }

    /**
     * 服务器出现错误
     */
    public void onServerError() {
        ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.server_error));
        onCallBack(HttpConfig.HTTP_STATUS_CODE_SERVER_ERROR, null);
    }


    /**
     * 连接超时
     */
    public void onConnectTimeOut() {
        ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.net_time_out));
        onCallBack(HttpConfig.HTTP_STATUS_CODE_NET_TIME_OUT, null);
    }

    /**
     * 网络错误
     */
    public void onNetError() {
        ToastUtil.showMessage(isToast, mActivity, mActivity.getString(R.string.network_connect_error));
        onCallBack(HttpConfig.HTTP_STATUS_CODE_NET_ERROR, null);
    }

}
